import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Date;
import java.util.List;

import model.Group;
import model.User;


public class Client implements Runnable{
	private Socket socket;
	private boolean running;
	private Controller controller;
	
	public Client(Socket socket, Controller controller){
		this.socket = socket;
		this.controller = controller;
	}

	public void start(){
		if(socket != null && !running){
			new Thread(this).start();
			running = true;
		}
	}

	@Override
	public void run() {
		
		PrintWriter pw = null;
		BufferedReader br = null;
		
		try{
			br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			
			String data = br.readLine();
			System.out.println(new Date() + ":New Data from Android Device: " + data);
			
			//registrat the device token for a specific device
			if(data.startsWith("registration::")){//registration::deviceKey deviceId
				data = data.substring("registration::".length());
				String[] deviceInfo = data.split(" ");
				if(deviceInfo.length == 2){
					controller.addOrUpdateDevice(deviceInfo[1], deviceInfo[0]);
				}
			}
			//Used for testing
			else if(data.startsWith("test::")){//test::deviceId
				data = data.substring("test::".length());
				controller.test(data);
			}
			//Set a user on a device, if user don't exist, create user
			else if(data.startsWith("user::")){//user::name::deviceId
				data = data.substring("user::".length());
				String[] data2 = data.split("::");
				if(data2.length == 2){
					controller.setUserOnDevice(data2[0], data2[1]);
				}
			}
			//Update the users score
			else if(data.startsWith("score::")){//score::name::win::lost
				data = data.substring("score::".length());
				String[] data2 = data.split("::");
				if(data2.length == 3){
					controller.updateUserScore(data2[0], convertStringToInt(data2[1], 0), convertStringToInt(data2[2], 0));
				}
			}
			//Add a user to a group, if the group don't exist, create group
			else if(data.startsWith("groupAdd::")){//groupAdd::username::groupname
				data = data.substring("groupAdd::".length());
				String[] data2 = data.split("::");
				if(data2.length == 2){
					controller.addUserToGroup(data2[0], data2[1]);
				}
			}
			//Get GroupHighscore
			else if(data.startsWith("getGroupHighscore::")){//getGroupHighscore::groupname::nr
				data = data.substring("getGroupHighscore::".length());
				String[] data2 = data.split("::");
				pw = new PrintWriter(socket.getOutputStream());
				
				if(data2.length == 2){
					List<User> uList = controller.getGroupScore(data2[0], convertStringToInt(data2[1], 10));
					pw.println(data2[0] + "::" + uList.size());
					for(User u : uList){
						pw.println(u.getName() + "::" + u.getWin() + "::" + u.getLost());
					}
				}else{
					pw.println("length::0");
				}
				pw.flush();
			}
			//Get Groups player is member in
			else if(data.startsWith("getGroups::")){//getGroups::username
				data = data.substring("getGroups::".length());
				List<Group> gList = controller.getGroupsUserIsMemberIn(data);
				pw = new PrintWriter(socket.getOutputStream());
				pw.println("length::" + gList.size());
				for(Group g : gList){
					pw.println(g.getName());
				}
				pw.flush();
			}
			//Get Groups and user Highscore
			else if(data.startsWith("getHighscoreFromName::")){//getHighscoreFromName::username::nr
				data = data.substring("getHighscoreFromName::".length());
				String[] data2 = data.split("::");
				pw = new PrintWriter(socket.getOutputStream());
				if(data2.length == 2){
					List<Group> gList = controller.getGroupsUserIsMemberIn(data2[0]);
					int top = convertStringToInt(data2[1], 10);
					
					pw.println("groupLength::" + gList.size());
					System.out.println("groupLength::" + gList.size());
					for(Group g : gList){
						List<User> uList = controller.getGroupScore(g.getName(), top);
						pw.println(g.getName() + "::" + uList.size());
						System.out.println(g.getName() + "::" + uList.size());
						for(User u : uList){
							pw.println(u.getName() + "::" + u.getWin() + "::" + u.getLost());
							System.out.println(u.getName() + "::" + u.getWin() + "::" + u.getLost());
						}
					}
				}else{
					pw.println("groupLength::0");
				}
				pw.flush();
			}
//			groupLength::2
//				group1::3
//					user1::1::2
//					user2::0::5
//					user3::5::2
//				group2::1
//					user4::0::0
			
		} catch (IOException e){
			e.printStackTrace();
		} finally {
			if(pw != null){
				pw.close();
			}
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {}
			}
			if(socket != null){
				try {
					socket.close();
					socket = null;
				} catch (IOException e) {}
			}
		}
		
	}
	
	private int convertStringToInt(String string, int ifFailValue){
		if(string.matches("[0-9]+")){
			return Integer.parseInt(string);
		}
		return ifFailValue;
	}

}
